﻿using System;
using System.Data;
using Microsoft.SharePoint;

namespace SKN
{
    /// <summary>
    /// This class will have common methods for Audit settings
    /// </summary>
    public static class Audit
    {
        private static SPAuditMaskType GetCorrectAuditFlagValue(string auditFlags)
        {
            SPAuditMaskType auditMaskType = SPAuditMaskType.None;

            if (auditFlags.Length > 0)
            {
                if (auditFlags.Contains("CheckIn"))
                    auditMaskType |= SPAuditMaskType.CheckIn;

                if (auditFlags.Contains("CheckOut"))
                    auditMaskType |= SPAuditMaskType.CheckOut;
                if (auditFlags.Contains("ChildDelete"))
                    auditMaskType |= SPAuditMaskType.ChildDelete;
                if (auditFlags.Contains("Copy"))
                    auditMaskType |= SPAuditMaskType.Copy;
                if (auditFlags.Contains("Delete"))
                    auditMaskType |= SPAuditMaskType.Delete;
                if (auditFlags.Contains("Move"))
                    auditMaskType |= SPAuditMaskType.Move;
                if (auditFlags.Contains("ProfileChange"))
                    auditMaskType |= SPAuditMaskType.ProfileChange;
                if (auditFlags.Contains("SchemaChange"))
                    auditMaskType |= SPAuditMaskType.SchemaChange;
                if (auditFlags.Contains("Search"))
                    auditMaskType |= SPAuditMaskType.Search;
                if (auditFlags.Contains("SecurityChange"))
                    auditMaskType |= SPAuditMaskType.SecurityChange;
                if (auditFlags.Contains("Undelete"))
                    auditMaskType |= SPAuditMaskType.Undelete;
                if (auditFlags.Contains("Update"))
                    auditMaskType |= SPAuditMaskType.Update;
                if (auditFlags.Contains("View"))
                    auditMaskType |= SPAuditMaskType.View;
                if (auditFlags.Contains("Workflow"))
                    auditMaskType |= SPAuditMaskType.Workflow;
            }
            else
            {
                auditMaskType |= SPAuditMaskType.All;
            }

            return auditMaskType;
        }

        private static string GetUserNameById(SPWeb web, int userId)
        {
            if (userId == -1)
            {
                return @"SHAREPOINT\System";
            }
            else
            {
                return web.AllUsers.GetByID(userId).Name;
            }
        }

        /// <summary>
        /// Use this method to enable site collection level auditing
        /// </summary>
        /// <param name="site"></param>
        /// <param name="auditFlags">Pass the auditing flags separated by comma's</param>
        /// <example>Audit.EnableAuditing(site,"Copy,Delete");</example>
        public static void EnableAuditing(SPSite site, string auditFlags)
        {
            site.Audit.AuditFlags = GetCorrectAuditFlagValue(auditFlags);
            site.Audit.Update();
        }

        /// <summary>
        /// Use this method to enable list level auditing
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listName"></param>
        /// <param name="auditFlags">Pass the auditing flags separated by comma's</param>
        /// <example>Audit.EnableListAuditing(web,"Shared Documents","Copy,Delete");</example>
        public static void EnableListAuditing(SPWeb web, string listName, string auditFlags)
        {
            SPList list = web.Lists[listName];
            list.Audit.AuditFlags = GetCorrectAuditFlagValue(auditFlags);
            list.Audit.Update();
        }

        /// <summary>
        /// Use this method to disable auditing at site collection level
        /// </summary>
        /// <param name="site"></param>
        /// <example>Audit.DisableAuditing(site);</example>
        public static void DisableAuditing(SPSite site)
        {
            site.Audit.AuditFlags = SPAuditMaskType.None;
            site.Audit.Update();
        }

        /// <summary>
        /// Disable auditing at list level
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listName"></param>
        /// <example>Audit.DisableListAuditing(web,"Shared Documents");</example>
        public static void DisableListAuditing(SPWeb web, string listName)
        {
            SPList list = web.Lists[listName];
            list.Audit.AuditFlags = SPAuditMaskType.None;
            list.Audit.Update();
        }

        /// <summary>
        /// Use this method to read the audit data for the site collection
        /// </summary>
        /// <param name="site">Site Collection object</param>
        /// <example >DataTable dt = Audit.GetAuditData(site);</example>
        public static DataTable GetAuditData(SPSite site)
        {
            var wssQuery = new SPAuditQuery(site);
            SPAuditEntryCollection auditCol = site.Audit.GetEntries(wssQuery);

            var table = new DataTable();
            table.Columns.Add("User", typeof(string));
            table.Columns.Add("Event", typeof(string));
            table.Columns.Add("ItemType", typeof(string));
            table.Columns.Add("DocLocation", typeof(string));
            table.Columns.Add("Occurred", typeof(DateTime));
            table.Columns.Add("EventSource", typeof(string));

            using (SPWeb web = site.RootWeb)
            {
                foreach (SPAuditEntry entry in auditCol)
                {
                    DataRow newRow = table.Rows.Add();
                    newRow["User"] = GetUserNameById(web, entry.UserId);
                    newRow["Event"] = entry.Event;
                    newRow["ItemType"] = entry.ItemType.ToString();
                    newRow["DocLocation"] = entry.DocLocation;
                    newRow["Occurred"] = entry.Occurred.ToLocalTime();
                    newRow["EventSource"] = entry.EventSource;
                }
            }
            return table;
        }

        /// <summary>
        /// Use this method to get the Audit data restricted to a particular list
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        /// <example>DataTable dt = Audit.GetListAuditData(web,"Shared Documents");</example>
        public static DataTable GetListAuditData(SPWeb web, string listName)
        {
            DataTable table;

            using (SPSite site = web.Site)
            {
                SPList list = web.Lists[listName];
                var wssQuery = new SPAuditQuery(site);
                wssQuery.RestrictToList(list);
                SPAuditEntryCollection auditCol = site.Audit.GetEntries(wssQuery);

                table = new DataTable();
                table.Columns.Add("User", typeof(string));
                table.Columns.Add("Event", typeof(string));
                table.Columns.Add("ItemType", typeof(string));
                table.Columns.Add("DocLocation", typeof(string));
                table.Columns.Add("Occurred", typeof(DateTime));
                table.Columns.Add("EventSource", typeof(string));

                foreach (SPAuditEntry entry in auditCol)
                {
                    DataRow newRow = table.Rows.Add();
                    newRow["User"] = GetUserNameById(web, entry.UserId);
                    newRow["Event"] = entry.Event;
                    newRow["ItemType"] = entry.ItemType.ToString();
                    newRow["DocLocation"] = entry.DocLocation;
                    newRow["Occurred"] = entry.Occurred.ToLocalTime();
                    newRow["EventSource"] = entry.EventSource;
                }
            }

            return table;
        }
    }
}